#ifndef __ROUTING_IO_H__
#define __ROUTING_IO_H__ 1

#include <string>

#include <sys/select.h>
#include <arpa/inet.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#include <linux/icmp.h>
#include <linux/netfilter.h>

#include "sample_io.h"
#include "rtp_packet.h"

typedef int(*callbackFnct)(struct nfq_q_handle*, struct nfgenmsg*, struct nfq_data*, void*);

/*
 *
 * This class implements the real-time modification of VoIP-Data 
 * exchange. The read and write methods are non-blocking, in case 
 * there are no packets to process.
 *
 */
class CRoutingIO : public ISampleIO
{
	public:
		CRoutingIO() : 
			mConfig(NULL),
			mAddressEmbeddee(0),
			mAddressExtractee(0),
			/* current stream info is statically coded */
			mStreamInfo(NAudioFormats::U8, 8000, NAudioFormats::UNKNOWN_CODEC),
			mAction(EMBED),
			mNfq_handle(NULL),
			mNfq_q_handle(NULL),
			mNfq_fd(-1),
			mPacketLength(-1),
			mPacketID(-1),
			mPacketReady(false),
			mIPPacket(NULL),
			mRTPPacket(NULL)
			{ }
		virtual ~CRoutingIO() { }

		/* START methods inherited by ISampleIO */
		virtual int init(CPropertiesReader* pConfig);
		virtual int destroy();

		virtual int read(void** pData, EAction& pAction, int pTimeout/* = 500000*/);
		virtual int write(void* pData, const EAction& pAction, int pLength);

		virtual NAudioFormats::SStreamInfo getStreamInfo() { return mStreamInfo; }
		/* END methods inherited by ISampleIO */

		/**
		 * @brief return the IP-address of the embedding party
		 * @return IP-address of the embedding party as 32-bit integer
		 */
		inline uint32_t getAddressEmbeddee() const { return mAddressEmbeddee; }
		/**
		 * @brief return the IP-address of the extracting party
		 * @return IP-address of the extracting party as 32-bit integer
		 */
		inline uint32_t getAddressExtractee() const { return mAddressExtractee; }

		/**
		 * @brief debugging method for printing the packet's contents
     * @param pData pointer to the memory area representing the packet
		 * @param pLength length of the memory area in bytes
		 */
		void printCurrentPacket(uint8_t* pData, uint16_t pLength);


	private:
		CRoutingIO(const CRoutingIO& );
		CRoutingIO& operator=(const CRoutingIO& );

		static const std::string sIniSectionName;
		static const std::string sConfAddressEmbedee;
		static const std::string sConfAddressExtractee;
		static const std::string sConfNfqueueNum;
		static const int sBytesPerLine;
		CPropertiesReader* mConfig;

		/* internal data */
		uint32_t mAddressEmbeddee;
		uint32_t mAddressExtractee;
		struct NAudioFormats::SStreamInfo mStreamInfo;
		EAction mAction;

		/* NFQUEUE handles */
		struct nfq_handle* mNfq_handle;
		struct nfq_q_handle* mNfq_q_handle;
		int mNfq_fd;
		int mPacketLength;
		int mPacketID;
		volatile bool mPacketReady;

		CIPPacket* mIPPacket;
		CRTPPacket* mRTPPacket;

		/* NFQUEUE callback */
		static int callback(struct nfq_q_handle *pNfq_q_handle, struct nfgenmsg* pNf_gen_msg, struct nfq_data* pNfq_data, void* pData);
		int callback(struct nfq_q_handle *pNfq_q_handle, struct nfgenmsg* pNf_gen_msg, struct nfq_data* pNfq_data);

		/* helpers */
		int32_t get_address(const char* pSection, const char* pKey, uint32_t* pAddress);
};

#endif /* __ROUTING_IO_H__ */

